package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.api.dto.leanring.LearningRecordFormDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.LearningRecord;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.until.LearningRecordDelayTaskHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

import static com.tianji.learning.enums.LessonStatus.*;
import static com.tianji.learning.enums.SectionType.VIDEO;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author 大扒鸭
 * @since 2025-06-28
 */
@Service
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {
    @Autowired
    private ILearningLessonService lessonService;
    @Autowired
    private CourseClient courseClient;
    @Autowired
    private LearningRecordDelayTaskHandler taskHandler;
    // 查询当前用户指定课程的学习进度
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
//        1.获取用户id
        Long userid = UserContext.getUser();
        // 2.查询课表
        LearningLesson learningLesson = lessonService.queryByUserAndCourseId(userid, courseId);
        // 3.查询学习记录
        List<LearningRecord> list = lambdaQuery().eq(LearningRecord::getLessonId, learningLesson.getId()).list();
        // 4.封装结果
        LearningLessonDTO dto = new LearningLessonDTO();
        dto.setId(learningLesson.getId());
        dto.setLatestSectionId(learningLesson.getCourseId());
        dto.setRecords(BeanUtils.copyList(list, LearningRecordDTO.class));
//        5.返回结果
        return dto;
    }
    // 提交学习记录
    @Override
    public void addLearningRecord(LearningRecordFormDTO formDTO) {
        // 判断是考试还是视频
        boolean finish = formDTO.getSectionType() == VIDEO.getValue() ? addVideoRecord(formDTO) : addExamRecord(formDTO);
        if (! finish){
            // 没有学完的小节无需提交
            return;
         }
        // 提交课表数据
        handleLearningLesson(formDTO, finish);
    }

    private void handleLearningLesson(LearningRecordFormDTO formDTO, boolean finish) {
        // 1、查询课表数据（已学习小节数、课程ID）
        LearningLesson record = lessonService.getById(formDTO.getLessonId());
        AssertUtils.isNotNull(record, "课表数据不存在");
        // 2、查询课程数据，判断是否全部学完所有小节
        boolean allFinished = false;
        if (finish) {
            // 2.1、查询课程数据
            CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(record.getCourseId(), false, false);
            AssertUtils.isNotNull(courseInfoById, "课程数据不存在");
            // 2.2、比较（已完成小节数 + 1 >= 课程总小节数）
           allFinished = record.getLearnedSections() + 1 >= courseInfoById.getSectionNum();

        }
        // 更新课表数据
        boolean update = lessonService.lambdaUpdate().set(LearningLesson::getLatestSectionId, formDTO.getSectionId())
                .set(LearningLesson::getLatestLearnTime, formDTO.getCommitTime())
                //.set(LearningLesson::getLearnedSections, lesson.getLearnedSections() + 1)
                .setSql(finish, "learned_sections = learned_sections + 1")
                .set(allFinished, LearningLesson::getStatus, FINISHED)
                .set(record.getStatus() == NOT_BEGIN.getValue(), LearningLesson::getStatus, LEARNING)
                .eq(LearningLesson::getId, formDTO.getLessonId())
                .update();
        if (!update){
            throw new BizIllegalException("提交课表数据错误");
        }
    }

    private boolean addExamRecord(LearningRecordFormDTO formDTO) {
        // 将DTO转为实体
        LearningRecord record = BeanUtil.toBean(formDTO, LearningRecord.class);
        // 填充数据
        record.setFinished(true);
        record.setUserId(UserContext.getUser());
        record.setFinishTime(formDTO.getCommitTime());
        // 存入数据库
        boolean save = save(record);
        if (!save){
            throw new DbException("保存考试记录失败");
        }
        return true;
    }

    // 添加视频学习记录
    private boolean addVideoRecord(LearningRecordFormDTO formDTO) {
        // 1、查询旧的学习记录
        // select * from learning_record where lesson_id = ? and section_id = ?
        LearningRecord old = queryOldRecord(formDTO.getLessonId(), formDTO.getSectionId());

        // 2、判断学习记录是否存在
        if (ObjectUtil.isEmpty(old)){
            // 3、如果不存在，新增学习记录
            // 3.1、将DTO 转化为 PO
            LearningRecord record = BeanUtil.toBean(formDTO, LearningRecord.class);
            // 3.2、填充缺失数据
            record.setUserId(UserContext.getUser());
            // 3.3、写入数据库
            boolean save = save(record);
            if (! save){
                throw new DbException("新增学习记录失败");
            }
            // 3.4、返回是否是第一次学完的标识
            return false;
        }
        // 4、如果存在，更新学习记录
        // 4.1、判断是否是第一次学完当前小节
        boolean firstFinished = !old.getFinished() && formDTO.getMoment() << 1 > old.getMoment();
        if (!firstFinished) {
            LearningRecord record = new LearningRecord();
            record.setLessonId(formDTO.getLessonId());
            record.setSectionId(formDTO.getSectionId());
            record.setMoment(formDTO.getMoment());
            record.setId(old.getId());
            record.setFinished(old.getFinished());
            taskHandler.addLearningRecordTask(record);
            return false;
        }
        // 4.2、更新学习记录（一定要更新的字段：moment，第一次学完时更新的两个字段：finished、finish_time）
        boolean update = lambdaUpdate().set(LearningRecord::getMoment, formDTO.getMoment())
                .set(firstFinished, LearningRecord::getFinished, true)
                .set(firstFinished, LearningRecord::getFinishTime, formDTO.getCommitTime())
                .eq(LearningRecord::getId, old.getId())
                .update();
        if (! update){
            throw new DbException("更新学习记录失败");
        }
        // 删除缓存
        taskHandler.cleanRecordCache(formDTO.getLessonId(),formDTO.getSectionId());
        return false;
    }
    // 查询旧学习记录
    private LearningRecord queryOldRecord(Long lessonId, Long sectionId) {
        // 1.查询缓存
        LearningRecord record = taskHandler.readRecordCache(lessonId, sectionId);
        // 2.如果命中，直接返回
        if (record != null) {
            return record;
        }
        // 3.未命中，查询数据库
        record = lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId)
                .eq(LearningRecord::getSectionId, sectionId)
                .one();
        // 4.写入缓存
        taskHandler.writeRecordCache(record);
        return record;
    }
}


